package com.cqjtu.eecs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cqjtu.eecs.entity.*;
import com.cqjtu.eecs.entity.dto.AttendedCourseDto;
import com.cqjtu.eecs.entity.dto.StudentScoreName;
import com.cqjtu.eecs.entity.vo.ClassAnalysisVo;
import com.cqjtu.eecs.entity.vo.CourseScoreVo;
import com.cqjtu.eecs.entity.vo.StudentAnalysis;
import com.cqjtu.eecs.entity.vo.StudentAnalysisVo;
import com.cqjtu.eecs.exception.NotFoundException;
import com.cqjtu.eecs.mapper.*;
import com.cqjtu.eecs.service.IAnalysisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @description: 成绩分析服务类
 * @author: 徐文升
 * @create: 2022-03-20 13:24
 **/

@Service
public class AnalysisService implements IAnalysisService {

    @Autowired
    private NaturalClassMapper naturalClassMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private AnalysisMapper analysisMapper;

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private RequirementMapper requirementMapper;

    @Autowired
    private CourseGoalMapper courseGoalMapper;

    @Autowired
    private RequirementServiceImpl requirementService;

    @Autowired
    private CourseGoalScoreMapper courseGoalScoreMapper;

    @Override
    public ClassAnalysisVo getClassAnalysis(String className, Integer grade, String majorCode) {
        ClassAnalysisVo classAnalysisVo = new ClassAnalysisVo();
        Project project = projectMapper.selectOne(new QueryWrapper<Project>().eq("grade", grade).eq("major_code", majorCode));
        if (project == null)
            throw new NotFoundException("培养方案未导入，请联系系主任");

        List<Requirement> requirementList = requirementMapper.selectList(new QueryWrapper<Requirement>().eq("pid", project.getPid()).isNotNull("pre_requirement_id"));
        classAnalysisVo.setTargetNum(requirementList.size());


        NaturalClass naturalClass = naturalClassMapper.selectOne(new QueryWrapper<NaturalClass>()
                .eq("natural_class_name", className)
                .eq("grade", grade)
                .eq("major_code", majorCode));
        if (naturalClass == null)
            throw new NotFoundException(className + "不存在");

        Integer ncId = naturalClass.getNcId();

        classAnalysisVo.setClassName(className);

        // 查询学生总数
        Integer stuNum = studentMapper.selectCount(new QueryWrapper<Student>().eq("nc_id", ncId));
        classAnalysisVo.setStuNum(stuNum);

        // 查询不及格率
        Integer flunkNum = studentMapper.getFlunkNum(ncId);
        classAnalysisVo.setFlunkDegree((stuNum == 0 ? 0 : flunkNum / stuNum) + "%");

        // 查询自然班已修读总课程门数和学分
        AttendedCourseDto attendedCourseDto = analysisMapper.getAttendedCourseDto(ncId);
        classAnalysisVo.setAttendedCourse(attendedCourseDto.getAttendedCourse());
        classAnalysisVo.setCredit(attendedCourseDto.getCredit());

        List<CourseScoreVo> courseScoreNameList = analysisMapper.getCourseScoreName(ncId);
        int courseNum = courseScoreNameList.size();
        courseScoreNameList.forEach(item -> {
            item.setScore(item.getScore() / stuNum);
        });
        if (courseNum != 0 && stuNum != 0) {
            classAnalysisVo.setAvgMax(courseScoreNameList.get(0).getScore());
            classAnalysisVo.setAvgMaxCourseName(courseScoreNameList.get(0).getCourseName());
            classAnalysisVo.setAvgMin(courseScoreNameList.get(courseNum - 1).getScore());
            classAnalysisVo.setAvgMinCourseName(courseScoreNameList.get(courseNum - 1).getCourseName());

            classAnalysisVo.setCourseAvgScoreList(courseScoreNameList);

            StudentScoreName avgMax = analysisMapper.getAvgStudent(ncId, true);
            classAnalysisVo.setStuAvgMax(avgMax.getScore() / attendedCourseDto.getAttendedCourse());
            classAnalysisVo.setStuAvgMaxName(avgMax.getName());

            StudentScoreName avgMin = analysisMapper.getAvgStudent(ncId, false);
            classAnalysisVo.setStuAvgMin(avgMin.getScore() / attendedCourseDto.getAttendedCourse());
            classAnalysisVo.setStuAvgMinName(avgMin.getName());
        }

        List<Integer> courseIdList = analysisMapper.getAttendedCourseIdList(courseScoreNameList);
        this.setSupport(courseIdList, requirementList, classAnalysisVo);
        return classAnalysisVo;
    }

    /**
     * 根据学号查询学生毕业要求雷达图数据
     * @param studentCode
     * @return
     */
    @Override
    public StudentAnalysisVo getStudentRadarGraphData(String studentCode) {
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("stu_code", studentCode));
        // 获取自然班的学生人数
        Integer stuNum = studentMapper.selectCount(new QueryWrapper<Student>().eq("nc_id", student.getNcId()));

        // 获取该专业所有毕业要求二级指标点
        List<Requirement> requirementList = requirementService.getRequirementListByMajorNameAndGrade(student.getMajorCode(), student.getGrade());

        List<StudentAnalysis> studentAnalysisList = new ArrayList<>();

        // 低于评价达成度5%的指标点
        List<String> targets = new ArrayList<>();
        // 建议加强学习的课程编号
        Set<Integer> courseIds = new HashSet<>();

        // 遍历每个毕业要求二级指标点
        requirementList.forEach(requirement -> {
            StudentAnalysis studentAnalysis = new StudentAnalysis();
            studentAnalysis.setName("B" + requirement.getRequirementCode());
            // 支撑毕业要求的所有课程目标
            List<CourseGoal> courseGoalList = courseGoalMapper.selectList(new QueryWrapper<CourseGoal>().eq("requirement_id", requirement.getRequirementId()));

            float achieveValue = 0f;
            float reachValue = 0f;
            float studentAchieveValue = 0f;
            for (CourseGoal courseGoal : courseGoalList) {
                CourseGoalScore courseGoalScore = courseGoalScoreMapper.selectOne(new QueryWrapper<CourseGoalScore>().eq("course_goal_id", courseGoal.getCourseGoalId())
                        .eq("sid", student.getSid()));
                studentAchieveValue += courseGoalScore.getContributionValue();
                achieveValue += courseGoal.getWeight();
                Double contributionSum = courseGoalScoreMapper.getContributionSumOfNaturalClass(courseGoal.getCourseGoalId(), student.getNcId());
                if (contributionSum != null) {
                    reachValue += (contributionSum / stuNum);
                }
            }

            float compare = 0;
            if (studentAchieveValue != 0 || achieveValue != 0) {
                compare = (reachValue - studentAchieveValue) * 100.0f / achieveValue;
            }
            if (compare >= 5) {
                targets.add(requirement.getRequirementCode());
                List<Integer> enhancedCourses = this.getEnhancedCourseId(requirement.getRequirementId());
                courseIds.addAll(enhancedCourses);
            }

            studentAnalysis.setAchieveValue(String.format("%.1f", achieveValue * 100));
            studentAnalysis.setReachValue(String.format("%.1f", reachValue * 100));
            studentAnalysis.setStudentAchieveValue(String.format("%.1f", studentAchieveValue * 100));
            float degree;
            float studentDegree;
            if (achieveValue == 0) {
                degree = 0;
                studentDegree = 0;
            }
            else {
                degree = (reachValue / achieveValue);
                studentDegree = (reachValue / achieveValue);
            }

            studentAnalysis.setDegree(String.format("%.1f", degree * 100));
            studentAnalysis.setStudentDegree(String.format("%.1f", studentDegree * 100));
            studentAnalysisList.add(studentAnalysis);
        });
        List<Integer> tcIds = analysisMapper.getTeachClassBySid(student.getSid());
        List<String> attendedCourse = analysisMapper.getCourseNamesByTcIds(tcIds);
        // 建议加强学习的课程名
        List<String> courses = new ArrayList<>();
        if (!courseIds.isEmpty())
            courses = analysisMapper.getEnhancedCourseName(courseIds, attendedCourse);
        StudentAnalysisVo studentAnalysisVo = new StudentAnalysisVo();
        studentAnalysisVo.setStudentAnalysisList(studentAnalysisList);
        studentAnalysisVo.setTargets(targets);
        studentAnalysisVo.setCourses(courses);
        return studentAnalysisVo;
    }

    private List<Integer> getEnhancedCourseId(Integer requirementId) {
        return analysisMapper.getCourseIdByRequirementId(requirementId);
    }

    private void setSupport(List<Integer> courseIdList, List<Requirement> requirementList, ClassAnalysisVo classAnalysisVo) {
        int whole = 0, part = 0, allNot = 0;
        try {
            for (Requirement requirement : requirementList) {
                List<Integer> requirementCourse = analysisMapper.getCourseIdByRequirementId(requirement.getRequirementId());
                int cnt = 0;
                for (Integer course : requirementCourse) {
                    if (courseIdList.contains(course))
                        cnt++;
                }
                if (cnt == 0)
                    allNot++;
                else if (cnt == requirementCourse.size())
                    whole++;
                else
                    part++;
            }
            classAnalysisVo.setWholeSupport(whole);
            classAnalysisVo.setPartSupport(part);
            classAnalysisVo.setNotSupport(allNot);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
